/*
 * Public include file
 *
 * Copyright (c) 2019 Virtuozzo International GmbH
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met :
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and / or other materials provided with the distribution.
 * 3. Neither the names of the copyright holders nor the names of their contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
#if !defined(PUBLIC_H)
#define PUBLIC_H

#define VIOSOCK_SYMLINK_NAME          L"\\DosDevices\\Viosock"

#define FILE_DEVICE_SOCKET            0x0801

#define DEFINE_SOCKET_IOCTL(Function) CTL_CODE(FILE_DEVICE_SOCKET, 0x800 | (Function), METHOD_BUFFERED, FILE_ANY_ACCESS)
#define DEFINE_DEVICE_IOCTL(Function) CTL_CODE(FILE_DEVICE_SOCKET, 0xC00 | (Function), METHOD_BUFFERED, FILE_ANY_ACCESS)

// device ioctls
#define IOCTL_GET_CONFIG              DEFINE_DEVICE_IOCTL(1)
#define IOCTL_SELECT                  DEFINE_DEVICE_IOCTL(2)
#define IOCTL_GET_AF                  DEFINE_DEVICE_IOCTL(3)

// socket ioctls
#define IOCTL_SOCKET_BIND             DEFINE_SOCKET_IOCTL(1)
#define IOCTL_SOCKET_CONNECT          DEFINE_SOCKET_IOCTL(2)
#define IOCTL_SOCKET_READ             CTL_CODE(FILE_DEVICE_SOCKET, 0x800 | (3), METHOD_OUT_DIRECT, FILE_READ_ACCESS)
#define IOCTL_SOCKET_SHUTDOWN         DEFINE_SOCKET_IOCTL(4)
#define IOCTL_SOCKET_LISTEN           DEFINE_SOCKET_IOCTL(5)
#define IOCTL_SOCKET_ENUM_NET_EVENTS  DEFINE_SOCKET_IOCTL(6)
#define IOCTL_SOCKET_EVENT_SELECT     DEFINE_SOCKET_IOCTL(7)
#define IOCTL_SOCKET_GET_PEER_NAME    DEFINE_SOCKET_IOCTL(8)
#define IOCTL_SOCKET_GET_SOCK_NAME    DEFINE_SOCKET_IOCTL(9)
#define IOCTL_SOCKET_GET_SOCK_OPT     DEFINE_SOCKET_IOCTL(10)
#define IOCTL_SOCKET_SET_SOCK_OPT     DEFINE_SOCKET_IOCTL(11)
#define IOCTL_SOCKET_IOCTL            DEFINE_SOCKET_IOCTL(12)

/*VSOCK address family value*/
#ifndef AF_VSOCK
#define AF_VSOCK 40
#endif

#ifndef PF_VSOCK
#define PF_VSOCK AF_VSOCK
#endif

#define VIRTIO_VSOCK_HOST_CID 2

typedef enum _VIRTIO_VSOCK_TYPE
{
    VIRTIO_VSOCK_TYPE_STREAM = 1,
} VIRTIO_VSOCK_TYPE;

typedef struct _VIRTIO_VSOCK_PARAMS
{
    ULONGLONG Socket;
    VIRTIO_VSOCK_TYPE Type;
} VIRTIO_VSOCK_PARAMS, *PVIRTIO_VSOCK_PARAMS;

#ifndef MSG_PEEK
#define MSG_PEEK 0x2
#endif

#ifndef MSG_WAITALL
#define MSG_WAITALL 0x8
#endif

typedef struct _VIRTIO_VSOCK_READ_PARAMS
{
    ULONG Flags;
} VIRTIO_VSOCK_READ_PARAMS, *PVIRTIO_VSOCK_READ_PARAMS;

// microsecs to 100-nanosec intervals
#define USEC_TO_NANO(us) ((LONGLONG)(us)*10)
// millisecs to 100-nanosec intervals
#define MSEC_TO_NANO(ms) (USEC_TO_NANO(ms) * 1000)
// secs to 100-nanosec intervals
#define SEC_TO_NANO(s)   (MSEC_TO_NANO(s) * 1000)

// 100-nanosec intervals to microsecs
#define NANO_TO_USEC(ns) ((LONGLONG)(ns) / 10)
// 100-nanosec intervals to millisecs
#define NANO_TO_MSEC(ns) (NANO_TO_USEC(ns) / 1000)
// 100-nanosec intervals to secs
#define NANO_TO_SEC(ns)  (NANO_TO_MSEC(ns) / 1000)

#ifndef FD_MAX_EVENTS
#define FD_MAX_EVENTS 10
#endif

#ifndef FD_ALL_EVENTS
#define FD_ALL_EVENTS ((1 << FD_MAX_EVENTS) - 1)
#endif

typedef struct _VIRTIO_VSOCK_NETWORK_EVENTS
{
    ULONG NetworkEvents;
    NTSTATUS Status[FD_MAX_EVENTS];
} VIRTIO_VSOCK_NETWORK_EVENTS, *PVIRTIO_VSOCK_NETWORK_EVENTS;

typedef struct _VIRTIO_VSOCK_EVENT_SELECT
{
    ULONGLONG hEventObject;
    long lNetworkEvents;
} VIRTIO_VSOCK_EVENT_SELECT, *PVIRTIO_VSOCK_EVENT_SELECT;

typedef struct _VIRTIO_VSOCK_OPT
{
    int level;
    int optname;
    ULONGLONG optval;
    int optlen;
} VIRTIO_VSOCK_OPT, *PVIRTIO_VSOCK_OPT;

typedef struct _VIRTIO_VSOCK_IOCTL_IN
{
    ULONG dwIoControlCode;
    ULONG cbInBuffer;
    ULONGLONG lpvInBuffer;
} VIRTIO_VSOCK_IOCTL_IN, *PVIRTIO_VSOCK_IOCTL_IN;

#ifndef FD_SETSIZE
#define FD_SETSIZE 64
#endif /* FD_SETSIZE */

typedef enum _VIRTIO_VSOCK_FDSET_TYPE
{
    FDSET_READ,
    FDSET_WRITE,
    FDSET_EXCPT,
    FDSET_MAX
} VIRTIO_VSOCK_FDSET_TYPE;

typedef struct _VIRTIO_VSOCK_FD_SET
{
    UINT fd_count;                  /* how many are SET? */
    ULONGLONG fd_array[FD_SETSIZE]; /* an array of SOCKETs */
} VIRTIO_VSOCK_FD_SET, *PVIRTIO_VSOCK_FD_SET;

typedef struct _VIRTIO_VSOCK_SELECT
{
    VIRTIO_VSOCK_FD_SET Fdss[FDSET_MAX];
    LONGLONG Timeout;
} VIRTIO_VSOCK_SELECT, *PVIRTIO_VSOCK_SELECT;

#endif /* PUBLIC_H */
